using Game.Main.Model;
using Game.Utils;
using SimpleJSON;
using UnityEngine;

namespace Game.Component
{
	public class PaintBoardItem : BaseItem
	{
		private Sprite sprite;

		private Texture2D texture;

		private int texWidth;

		private int texHeight;

		private int boardWidth;

		private int boardHeight;

		private int brushSize = 5;

		private float boardX;

		private float boardY;

		private float scaleX;

		private float scaleY;

		private byte[] pixels;

		private bool textureNeedsUpdate;

		private int clrFingerId = -1;

		public Color32 paintColor;

		private Vector2 oldUV = default(Vector2);

		private Vector2 curUV = default(Vector2);

		private int x0;

		private int y0;

		private int x1;

		private int y1;

		private int dx;

		private int dy;

		private int sx;

		private int sy;

		private int err;

		private int minDistance;

		private int pixelCount;

		private int e2;

		private bool loopDraw;

		private int r2;

		private int area;

		private int rr;

		private int tx;

		private int ty;

		private int pixel;

		public override void Init(ItemArchiveData data)
		{
			base.Init(data);
			Sprite sprite = model.GetComponent<SpriteRenderer>().sprite;
			texture = sprite.texture;
			texWidth = texture.width;
			texHeight = texture.height;
			scaleX = model.localScale.x;
			scaleY = model.localScale.y;
			boardWidth = (int)((float)texture.width * scaleX);
			boardHeight = (int)((float)texture.height * scaleY);
			boardX = (float)boardWidth / 100f;
			boardY = (float)boardHeight / 100f;
			if (!string.IsNullOrEmpty(data.pixels))
			{
				pixels = Compressor.UncompressToBytes(data.pixels);
			}
			if (pixels == null || pixels.Length != texWidth * texHeight * 3)
			{
				pixels = new byte[texWidth * texHeight * 3];
				int num = 0;
				for (int i = 0; i < texWidth; i++)
				{
					for (int j = 0; j < texHeight; j++)
					{
						pixels[num] = byte.MaxValue;
						pixels[num + 1] = byte.MaxValue;
						pixels[num + 2] = byte.MaxValue;
						num += 3;
					}
				}
			}
			else
			{
				textureNeedsUpdate = true;
				UpdateTexture();
			}
			paintColor = data.color;
		}

		protected override void LateUpdate()
		{
			UpdateTexture();
		}

		private void UpdateTexture()
		{
			if (textureNeedsUpdate)
			{
				textureNeedsUpdate = false;
				texture.LoadRawTextureData(pixels);
				texture.Apply(false);
			}
		}

		public override void TouchDown(TouchEventData touchEventData)
		{
			PaintDown(touchEventData, paintColor);
		}

		public void PaintDown(TouchEventData touchEventData, Color32 color)
		{
			if (clrFingerId < 0)
			{
				clrFingerId = touchEventData.fingerId;
				curUV.x = CheckPixelX((int)((touchEventData.curPos.x - model.position.x + boardX / 2f) * 100f / scaleX));
				curUV.y = CheckPixelY((int)((touchEventData.curPos.y - model.position.y + boardY / 2f) * 100f / scaleY));
				oldUV = curUV;
				Paint(oldUV, curUV, color);
			}
		}

		public override void TouchMove(TouchEventData touchEventData)
		{
			PaintMove(touchEventData, paintColor);
		}

		public void PaintMove(TouchEventData touchEventData, Color32 color)
		{
			if (clrFingerId == touchEventData.fingerId)
			{
				Paint(touchEventData, color);
			}
		}

		public override void TouchUp(TouchEventData touchEventData)
		{
			PaintUp(touchEventData, paintColor);
		}

		public void PaintUp(TouchEventData touchEventData, Color32 color)
		{
			if (clrFingerId == touchEventData.fingerId)
			{
				clrFingerId = -1;
				Paint(touchEventData, color);
			}
		}

		private void Paint(TouchEventData touchEventData, Color color)
		{
			oldUV = curUV;
			curUV.x = CheckPixelX((int)((touchEventData.curPos.x - model.position.x + boardX / 2f) * 100f / scaleX));
			curUV.y = CheckPixelY((int)((touchEventData.curPos.y - model.position.y + boardY / 2f) * 100f / scaleY));
			Paint(oldUV, curUV, color);
		}

		public void Eraser(Vector2 startPoint, Vector2 endPoint)
		{
			Vector2 start = default(Vector2);
			Vector2 end = default(Vector2);
			start.x = CheckPixelX((int)((startPoint.x - model.position.x + boardX / 2f) * 100f / scaleX));
			start.y = CheckPixelY((int)((startPoint.y - model.position.y + boardY / 2f) * 100f / scaleY));
			end.x = CheckPixelX((int)((endPoint.x - model.position.x + boardX / 2f) * 100f / scaleX));
			end.y = CheckPixelY((int)((endPoint.y - model.position.y + boardY / 2f) * 100f / scaleY));
			DrawRect(start, end, new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, 0));
			textureNeedsUpdate = true;
		}

		private void Paint(Vector2 startPoint, Vector2 endPoint, Color32 color)
		{
			if (Vector2.Distance(endPoint, startPoint) > (float)brushSize)
			{
				DrawLine(startPoint, endPoint, color);
			}
			else
			{
				DrawCircle((int)endPoint.x, (int)endPoint.y, color);
			}
			textureNeedsUpdate = true;
		}

		private void DrawRect(Vector2 start, Vector2 end, Color32 color)
		{
			x0 = (int)start.x;
			y0 = (int)start.y;
			x1 = (int)end.x;
			y1 = (int)end.y;
			for (int i = x0; i < x1; i++)
			{
				for (int j = y0; j < y1; j++)
				{
					pixel = (texWidth * j + i) * 3;
					pixels[pixel] = color.r;
					pixels[pixel + 1] = color.g;
					pixels[pixel + 2] = color.b;
				}
			}
		}

		private void DrawLine(Vector2 start, Vector2 end, Color32 color)
		{
			x0 = (int)start.x;
			y0 = (int)start.y;
			x1 = (int)end.x;
			y1 = (int)end.y;
			dx = Mathf.Abs(x1 - x0);
			dy = Mathf.Abs(y1 - y0);
			if (x0 < x1)
			{
				sx = 1;
			}
			else
			{
				sx = -1;
			}
			if (y0 < y1)
			{
				sy = 1;
			}
			else
			{
				sy = -1;
			}
			err = dx - dy;
			loopDraw = true;
			minDistance = brushSize >> 1;
			pixelCount = 0;
			e2 = 0;
			while (loopDraw)
			{
				pixelCount++;
				if (pixelCount > minDistance)
				{
					pixelCount = 0;
					DrawCircle(x0, y0, color);
				}
				if (x0 == x1 && y0 == y1)
				{
					loopDraw = false;
				}
				e2 = 2 * err;
				if (e2 > -dy)
				{
					err -= dy;
					x0 += sx;
				}
				if (e2 < dx)
				{
					err += dx;
					y0 += sy;
				}
			}
		}

		public void DrawCircle(int x, int y, Color32 color)
		{
			pixel = 0;
			r2 = brushSize * brushSize;
			area = r2 << 2;
			rr = brushSize << 1;
			for (int i = 0; i < area; i++)
			{
				tx = i % rr - brushSize;
				ty = i / rr - brushSize;
				if (tx * tx + ty * ty < r2 && x + tx >= 0 && y + ty >= 0 && x + tx < texWidth && y + ty < texHeight)
				{
					pixel = (texWidth * (y + ty) + x + tx) * 3;
					pixels[pixel] = color.r;
					pixels[pixel + 1] = color.g;
					pixels[pixel + 2] = color.b;
				}
			}
		}

		private int CheckPixelX(int x)
		{
			if (x < 0)
			{
				return 0;
			}
			if (x > texWidth)
			{
				return texWidth;
			}
			return x;
		}

		private int CheckPixelY(int y)
		{
			if (y < 0)
			{
				return 0;
			}
			if (y > texWidth)
			{
				return texWidth;
			}
			return y;
		}

		public override void PackData(JSONObject obj)
		{
			base.PackData(obj);
			obj["61"] = Compressor.CompressToString(pixels);
			obj["30"] = paintColor.r;
			obj["31"] = paintColor.g;
			obj["32"] = paintColor.b;
		}
	}
}
